%% my_pp.erl
%%      Pretty printing of erlang abstract syntax trees (ASTs) into text 
%%      files like source code.
%%
%% Copyright (C) 2008, 2009 Gábor Fehér
%%
%% This file is part of ECT.
%% 
%% ECT is free software: you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published by
%% the Free Software Foundation, either version 3 of the License, or
%% (at your option) any later version.
%% 
%% ECT is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%% GNU General Public License for more details.
%% 
%% You should have received a copy of the GNU General Public License
%% along with ECT.  If not, see <http://www.gnu.org/licenses/>.
%%
-module(my_pp).
-export([gen/1, print/3, printforms/3]).

plain(L) ->
    lists:flatten(L).


%% FIXME: Erlang write operations accept embedded list of charactes, 
%%        there may be no need to flatten
%% Function: gen(Forms)
%% Purpose: converts an abstract syntax tree to a flat string representing its source code
%% Arguments: 
%%   Forms: erlang AST forms
%% Returns:
%%   a text string representing the source code of Forms
gen([]) ->
    [];
gen([F|Forms]) ->
    plain( erl_pp:form(F, fun(F1) -> F1 end) ) ++ gen(Forms).

%% Function: print0(S, FileName, Silent)
%% Purpose: writes a string into a file
%% Arguments: 
%%   S: string to write
%%   FileName: name of file to write into
%%   Silent: if true, the writing to the file will not happen
%% Returns: 
%%   the atom ok
%% Side-effects:
%%   if Silent =:= true, then nothing
%%   if Silent =:= false, then string S is written to file FileName, and 
%%                        a text message is output to the user
print0(S, FileName, Silent) ->
    if (Silent =:= false) ->
        file:write_file(FileName, S),
        io:format("item written to ~p~n", [FileName]);
       (true) ->
        ok
    end.

%% Function: print(F, FileName, Silent)
%% Purpose:
%%   Prints the source code representation of AST F, into the file named FileName.
%% Arguments: 
%%   F: forms representing the source code to write
%%   FileName: name of file to write into
%%   Silent: if true, the writing to the file will not happen
%% Returns: 
%%   the atom ok
%% Side-effects:
%%   if Silent =:= true, then nothing
%%   if Silent =:= false, then the source code of F is written to file FileName, and 
%%                        a text message is output to the user
print(F, FileName, Silent) ->
    print0(gen(F), FileName, Silent).

%% Function: printforms(Suffix, Forms, Options)
%% Purpose:
%%   Prints source code of a module, extracting name from Forms,
%%   with name suffix Suffix
%% Arguments: 
%%   Suffix: suffix of the name of file that will be written
%%   Forms: forms representing the source code to write
%%   Options: options passed to the compiler
%%               outdir determines the location of the written file
%%               ect_verbose must be present and be true, otherwise no action is taken in this function
%% Returns: 
%%   the atom ok
%% Side-effects:
%%   - If ect_verbose is not present/true in Options, then nothing
%%   - If it is present and true, then the source code of Forms is written to file:
%%      its path is outdir specified in Options
%%      its name starts with the module name specified in Forms
%%      its extension is specified by the string Suffix
printforms(Suffix, Forms, Options) ->
    Silent = not proplists:get_value(ect_verbose, Options, false),

    if (Silent =:= false) ->
        {outdir, OutDir} = proplists:lookup(outdir, Options),
        [{attribute, _, module, Module}] = 
            lists:filter(
                fun({attribute, _, module, _}) -> true;
                    (_) -> false
                end, Forms),
        print(Forms, OutDir++atom_to_list(Module)++Suffix, Silent);
    true ->
        ok
    end.

